home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
SMOOTH11.ARJ
/
SMOOTH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-10
|
22KB
|
793 lines
/*
NAME
smooth - split linear smoothing
SYNOPSIS
smooth [file] [options]
options are:
-a [step [start]] automatic abscissas
-b break smooth after each label
-c general curve
-f <num> fraction of points to use for each fitted value
(default .5)
-n <num> number of points to use for each fitted value
(default 50%)
-r print residuals rather than smoothed values
-s split linear fit rather than "lowness"
-xl take logs of x values before smoothing
-yl take logs of y values before smoothing
-zl take logs of z values before interpolating
(implies -3)
-3 3D case: x, y, and z given for each point
Default smoothing method is "lowness": robust locally weighted
regression & smoothing
METHODS
Lowness by W. S. Cleveland, and split linear fit by A. Owen
AUTHOR
James Van Zandt (jrv@mbunix.mitre.org)
*/
#include <stdio.h>
#include <math.h>
#define VERSION "1.10"
#define MAX_WINDOWS 6
#define MAX_POINTS 800
#define MAXLABELS 25
int resid=0; /* nonzero if residuals are requested */
int fraction_specified=1; /* nonzero if fit is to a specified fraction of
the given data points */
int number_specified=0; /* nonzero if fit is to a specified number of
the given data points */
double fraction_fitted=.5; /* fraction of points used for each fitted value */
int num_fitted; /* number of points used for each fitted value */
char *gmem();
/*
Split Linear Smoothing Algorithm
Given:
A list of window sizes, SizeList, and n pairs (x[i],y[i]) sorted on x,
Return:
the split linear smooth of y on x.
The general technique is due to Art Owen, who offers this discussion:
"You should feel free to experiment with the algorithm,
since it has some ad hoc parts. The essentials are: to use
uncentered windows of varying sizes along with the central
ones, to get zero weight on the worst fitting lines, and to
make the weight attached to a particular line size and
orientation vary smoothly as one traverses the data. We
tried to find a simple way to meet all of these goals; the
algorithm we settled on was the simplest that worked for
us.
...
"West and Chan et. al. are useful for getting numerically
stable updating formulae for the regressions."
references...
John Alan McDonald and Art B. Owen, "Smoothing with Split
Linear Fits", LCS Technical Report No. 7, SLAC-PUB 3423,
AD-A149032, Laboratory for Computational Statistics, Dept.
of Statistics, Stanford University, July 1984.
West, D.H.D., 1979, Updating Mean and Variance Estimates:
An Improved Method, Communications of the ACM, v 22, no. 9
p 532-535 (1979).
Chan, T.F., Golub, G.H., and Leveque, R.J., 1983,
Algorithms for Computing the Sample Variance: Analysis and
Recommendations, The American Statistician v 37, p 242-247
(1983).
IMPLEMENTATION
For general curves, the given x- and y- (and z-, if present)
points are regarded as functions of the distance along a
smoothed path.
The arrays take a lot of space. For n points, the number of
doubles is approximately 38*n, plus 2*n for general curve, plus
2*n for 3D case. For 100 points and 8 byte doubles, this means
at least 8*38*100=30400 bytes.
Execution time... 101 points took 151 seconds on 7.5 MHz V-20,
no 8087.
The updating formulas mentioned above are not used in this
program. The selection of window sizes (a geometric sequence)
is my own. -JVZ
*/
SplitLinearSmooth(SizeList,x,y,Smooth) int SizeList; double Smooth[],x[],y[];
{ int i;
BasicSplitLinearSmooth( SizeList, x, y, Smooth );
BasicSplitLinearSmooth( SizeList, x, Smooth, Smooth );
if(resid)
for (i=0; i<SizeList; i++)
Smooth[i] = y[i]-Smooth[i];
}
/*
Basic Split Linear Smooth Algorithm by Art Owen <owen@su-score>
Given:
A list of window sizes and n pairs (x[i],y[i]) sorted on x,
Return:
the basic split linear smooth of y on x.
*/
#define f(x,y,z) ff[((x)*sizes+(y))*3+(z)]
#define pmse(x,y,z) errors[((x)*sizes+(y))*3+(z)]
#define left 0
#define center 1
#define right 2
static double *ff, *errors;
BasicSplitLinearSmooth(n, x, y, Smooth) int n; double x[], y[], Smooth[];
{ int k, C, L, R, i, sizes, num, start, finish, o, ws;
int window_size[MAX_WINDOWS];
double err, del, alpha, beta, w_total, w, s, c;
double sum, sumx, sumxx, sumy, sumxy;
/*
window sizes must be _odd_ in this implementation
sizes are: 5, 11, 23, 47, ... 6*2^k-1
or else: 7, 15, 31, 63, ... 8*2^k-1
depending on the maximum number of points to be fitted
*/
for (i = num_fitted+1; i >= 8; i/=2) {}
if(i >= 6) i=6; else i=8;
for (sizes=0; i-1 <= num_fitted && sizes < MAX_WINDOWS; i *= 2)
window_size[sizes++]=i-1;
/* most of the memory is allocated by these two statements */
ff=(double *)gmem(n*sizes*3*sizeof(double));
errors=(double *)gmem(n*sizes*3*sizeof(double));
for (k=0; k<sizes; k++)
{sum=sumx=sumxx=sumy=sumxy=0.;
/* Initialize the regression-window data structure */
ws=window_size[k];
C = -(ws/2);
L = C - ws/2;
R = C + ws/2;
for ( ; L<n ; L++, C++, R++)
{
if ( R < n )
{/* update the regression-window with (x[R],y[R]) */
/* Update routines are described in West (1979) */
/* these are my guesses -JVZ */
sum+=1.; sumx+=x[R]; sumxx+=x[R]*x[R];
sumy+=y[R]; sumxy+=x[R]*y[R];
}
if ( L-1 >= 0 )
{/* downdate the regression-window with (x[L-1],y[L-1]) */
sum-=1.; sumx-=x[L-1]; sumxx-=x[L-1]*x[L-1];
sumy-=y[L-1]; sumxy-=x[L-1]*y[L-1];
}
if ( sum>=ws ) /* the window covers enough points */
{/* Fit linear regression coefs. alpha, beta */
alpha=(sumy*sumxx - sumx*sumxy)/(sum*sumxx - sumx*sumx);
beta=(sumxy - alpha*sumx)/sumxx;
if ( 0 <= R && R < n )
{f(R,k,left)= alpha + beta*x[R];
/* compute pmse(R,k,left) */
/*
pmse(i,k,o) =
( sum{j in W(i,k,o)-{i}} (y[j]-alpha-beta*x[j])^2) / ( |W(i,k,o)|-3 )
where W is the window of points.
*/
start=R-ws;
if(start<0) start=0;
if(R-start>3)
{err=0.;
for (i=start; i<R; i++)
{del = y[i]-alpha-beta*x[i];
err += del*del;
}
pmse(R,k,left) = err/(R-start-3);
}
}
if ( 0 <= C && C < n )
{f(C,k,center)= alpha + beta*x[C];
/* compute pmse(C,k,center) */
start=C-ws/2;
if(start<0) start=0;
finish=C+ws/2+1;
if(finish>n) finish=n;
if(finish-start>3)
{err=0.;
for (i=start; i<finish; i++)
{if(i==C) continue;
del = y[i]-alpha-beta*x[i];
err += del*del;
}
pmse(C,k,center) = err/(finish-start-3);
}
}
if ( 0 <= L )
{f(L,k,right)= alpha + beta*x[L];
/* compute pmse(L,k,right) */
err=0.;
finish=L+ws;
if(finish>n) finish=n;
if(finish-L>3)
{for (i=L; i<finish; i++)
{del = y[i]-alpha-beta*x[i];
err += del*del;
}
pmse(L,k,right) = err/(finish-L-3);
}
}
}
else /* window doesn't cover enough points */
{if( R<n ) pmse(R,k,left) = -1;
if( 0<=C && C<n ) pmse(C,k,center) = -1;
if( 0<=L ) pmse(L,k,right) = -1;
}
}
}
for (i=0; i<n; i++)
{/* pmse cutoff: c = Average{k,o} pmse(i,k,o) */
err=0.;
num=0;
for (k=0; k<sizes; k++)
for (o=0; o<3; o++)
if(pmse(i,k,o)>=0.) {err += pmse(i,k,o); num++;}
c=err/num;
s = w_total = 0.;
for (k=0; k<sizes; k++)
for (o=0; o<3; o++)
{err=pmse(i,k,o);
if(err>=0. && err<c) /* pmse is present, and below cutoff */
{w = (err-c)*(err-c);
s += w*f(i,k,o);
w_total += w;
}
}
/* Smooth[i] = sum{k,o} w(i,k,o)*f(i,k,o) / sum{k,o} w(i,k,o) */
Smooth[i]=s/w_total;
}
free(errors);
free(ff);
}
double abscissa=0.;
double abscissa_step=1.;
double *x, *y, *z, *xs, *ys, *zs, *path;
int xlog=0; /* nonzero if taking log of x values */
int ylog=0; /* nonzero if taking log of y values */
int zlog=0; /* nonzero if taking log of z values */
int debugging=0;
int split=0; /* nonzero if split linear smooth is requested */
int breaking=0; /* nonzero if breaking at labels */
int labels=0; /* number of labels in input data */
int threed=0; /* nonzero if 3D case (x, y, and z given for each point) */
int automatic_abscissas=0;
int abscissa_arguments=0;
int curve=0; /* nonzero if general curve permitted */
int x_arguments=0;
int n; /* number of MAX_POINTS in x, y, and ys */
int index_array[MAXLABELS]; /* indexes into x and y */
int *p_data=index_array;
int total=100;
FILE *ifile;
char *label_array[MAXLABELS];
char **p_text=label_array;
main(argc,argv) int argc; char **argv;
{ int nn,origin;
read_data(argc,argv);
/* check switch arguments */
if(fraction_specified)
{if(fraction_fitted<0. || fraction_fitted>1.)
{fprintf(stderr, "fraction fitted=%f must be in range 0 to 1\n",
fraction_fitted);
exit(1);
}
num_fitted = floor(fraction_fitted*n+.5);
}
nn = 1;
if(split) nn = 11;
if(num_fitted < nn || num_fitted > n)
{fprintf(stderr, "number of points fitted=%d must be in range %d...%d",
num_fitted, nn, n);
exit(1);
}
if(breaking && labels)
{origin=0;
while(labels--)
{p_data[0] -= origin;
nn=p_data[0]+1;
if(nn) curv0(nn,total);
origin += nn;
path += nn;
x += nn;
y += nn;
p_data++;
p_text++;
}
}
else
{curv0(n,total);
}
exit(0);
}
curv0(n,requested)
int n,requested;
{ int i, j, each, stop, seg=0;
double s, ds, xx, yy, zz;
if(n<5) /* just copy a short file */
{for (j=0; j<n; j++)
{if(!automatic_abscissas)
{xx=x[n-1]; if(xlog) xx=exp(xx);
printf("%g ", xx);
}
yy=y[n-1]; if(ylog) yy=exp(yy);
printf("%g ", yy);
if(threed)
{zz=z[n-1]; if(zlog) zz=exp(zz);
printf("%g ",zz);
}
if(j==p_data[seg]) printf(p_text[seg++]);
putchar('\n');
}
return;
}
if(split)
{if(curve)
{SplitLinearSmooth( n, path, x, xs);
SplitLinearSmooth( n, path, y, ys);
if(threed) SplitLinearSmooth(n, path, z, zs);
}
else
{SplitLinearSmooth( n, x, y, ys);
if(threed) SplitLinearSmooth( n, x, z, zs);
}
}
else /* lowness smooth */
{if(curve)
{lowness( n, path, x, xs);
lowness( n, path, y, ys);
if(threed) lowness(n, path, z, zs);
}
else
{lowness( n, x, y, ys);
if(threed) lowness( n, x, z, zs);
}
}
for (j=0; j<n; j++)
{if(!automatic_abscissas)
{xx = curve ? xs[j] : x[j];
printf("%g ", xlog ? exp(xx) : xx);
}
printf("%g ", ylog ? exp(ys[j]) : ys[j] );
if(threed) printf("%g ", zlog ? exp(zs[j]) : zs[j] );
if(j==p_data[seg]) printf(p_text[seg++]);
putchar('\n');
}
}
double mylog(x) double x;
{ if(x<=0.)
{fprintf(stderr, "can\'t take log of %f\n", x);
exit(1);
}
return log(x);
}
read_data(argc,argv) int argc; char **argv;
{ int i, j, length, skipping, ac;
double xx, yy, zz, d, *pd, sum, xp, yp, zp, xq, yq, zq;
char *s,*t, **av, *strchr();
#define BUFSIZE 256
static char buf[BUFSIZE+2];
argc--; argv++;
ac=argc; av=argv; argc=0;
while(ac>0)
{if(**av=='?') help();
else if(**av=='-' && (i=get_parameter( ac, av )) && i > 0)
{ac-=i; av+=i;
}
else {argv[argc++] = *av++; ac--;}
}
if(argc<1 || **argv=='-') ifile=stdin;
else
{if(argc>=1)
{ifile=fopen(argv[0],"r");
if(ifile==NULL) {printf("file %s not found\n",argv[0]); exit(1);}
argc--; argv++;
}
else help();
}
x=path=(double *)gmem(MAX_POINTS*sizeof(double));
y=(double *)gmem(MAX_POINTS*sizeof(double));
if(threed) z=(double *)gmem(MAX_POINTS*sizeof(double));
p_data[0]=-1;
skipping=2;
if(automatic_abscissas) skipping--;
if(threed) skipping++;
i=0;
while(i<MAX_POINTS)
{if(fgets(buf,BUFSIZE,ifile)==0)break;
buf[strlen(buf)-1]=0; /* zero out the line feed */
if(buf[0]==';') {printf("%s\n",buf); continue;} /* skip comment */
if(t = strchr(buf, ';')) *t=0; /* zap same-line comment */
for (t=buf; *t && isspace(*t); t++) {} /* find first nonblank char */
if(*t == 0) continue; /* skip blank lines */
if(automatic_abscissas)
{x[i]=abscissa;
abscissa+=abscissa_step;
if(threed) sscanf(buf,"%lf %lf",&y[i],&z[i]);
else sscanf(buf,"%lf",&y[i]);
if(ylog) y[i]=mylog(y[i]);
if(zlog) z[i]=mylog(z[i]);
}
else
{if(threed) sscanf(buf,"%lf %lf %lf",&x[i],&y[i],&z[i]);
else sscanf(buf,"%lf %lf",&x[i],&y[i]);
if(xlog) x[i]=mylog(x[i]);
if(ylog) y[i]=mylog(y[i]);
if(zlog) z[i]=mylog(z[i]);
}
s=buf; /* start looking for label */
for (j=skipping; j--; )
{while(*s==' ')s++; /* skip a number */
while(*s && (*s!=' '))s++;
}
while(*s==' ')s++;
if((length=strlen(s))&&(labels<MAXLABELS))
{if(*s=='\"') /* label in quotes */
{t=s+1;
while(*t && (*t!='\"')) t++;
t++;
}
else /* label without quotes */
{t=s;
while(*t && (*t!=' '))t++;
}
*t=0;
length=t-s;
p_data[labels]=i;
p_text[labels]=gmem(length+1);
if(p_text[labels]) strcpy(p_text[labels++],s);
}
i++;
}
n=i;
if(n <= 1) {fprintf(stderr, "too little data"); exit(1);}
if(breaking && (!labels || p_data[labels-1]!=n-1))
{p_data[labels]=i-1;
if(p_text[labels]=gmem(1)) *p_text[labels++]=0;
}
ys=(double *)gmem(n*sizeof(double));
if(threed) zs=(double *)gmem(n*sizeof(double));
if(curve)
{xs=(double *)gmem(n*sizeof(double));
path=(double *)gmem(n*sizeof(double));
path[0]=sum=0.;
if(threed)
{xp=4.*x[0]; yp=4.*y[0]; zp=4.*z[0];
for (i=1; i<n; i++)
{xq=x[i-1]+2.*x[i]+x[i+1];
yq=y[i-1]+2.*y[i]+y[i+1];
zq=z[i-1]+2.*z[i]+z[i+1];
xx=xq-xp;
yy=yq-yp;
zz=zq-zp;
path[i]=(sum+=sqrt(xx*xx + yy*yy + zz*zz));
xp=xq; yp=yq; zp=zq;
}
xq=4.*x[n-1]; yq=4.*y[n-1]; zq=4.*y[n-1];
xx=xq-xp;
yy=yq-yp;
zz=zq-zp;
path[i]=(sum+=sqrt(xx*xx + yy*yy + zz*zz));
}
else
{xp=4.*x[0]; yp=4.*y[0];
for (i=1; i<n-1; i++)
{xq=x[i-1]+2.*x[i]+x[i+1];
yq=y[i-1]+2.*y[i]+y[i+1];
xx=xq-xp;
yy=yq-yp;
path[i]=(sum+=sqrt(xx*xx + yy*yy));
xp=xq; yp=yq;
}
xq=4.*x[n-1]; yq=4.*y[n-1];
xx=xq-xp;
yy=yq-yp;
path[i]=(sum+=sqrt(xx*xx + yy*yy));
}
}
else if(split)
{for(i=1; i<n; i++)
{if(x[i]<=x[i-1])
{fprintf(stderr,
"ERROR: independent variable not strictly increasing\n");
exit(1);
}
}
}
else
{for(i=1; i<n; i++)
{if(x[i]<x[i-1])
{fprintf(stderr,
"ERROR: data must be sorted on x value\n");
exit(1);
}
}
}
}
/* get_parameter - process one command line option
(return # parameters used) */
get_parameter(argc,argv) int argc; char **argv;
{ int i, permitted;
double temp;
if(strcmp(*argv,"-a")==0)
{automatic_abscissas=1;
if(argc<2 || *argv[1]=='-') return 1; /* no negative step */
permitted=2;
if(argc<3 || *argv[2]=='-') permitted=1; /* no neg. starting abscissa */
i=get_double(argc,argv,permitted,&abscissa_step,&abscissa,&abscissa);
abscissa_arguments=i-1;
return i;
}
else if(strcmp(*argv, "-f")==0)
{i=get_double(argc, argv, 1, &fraction_fitted, &fraction_fitted, &fraction_fitted);
fraction_specified=1;
number_specified=0;
return i;
}
else if(strcmp(*argv, "-n")==0)
{i=get_double(argc, argv, 1, &temp, &temp, &temp);
fraction_specified=0;
number_specified=1;
num_fitted = temp;
return i;
}
else if(strcmp(*argv, "-b")==0) {breaking=1; return 1;}
else if(strcmp(*argv, "-c")==0) {curve=1; return 1;}
else if(strcmp(*argv, "-d")==0) {debugging=1; return 1;}
else if(strcmp(*argv, "-r")==0) {resid=1; return 1;}
else if(strcmp(*argv, "-s")==0) {split=1; return 1;}
else if(strcmp(*argv,"-xl")==0) {xlog++; return 1;}
else if(strcmp(*argv,"-yl")==0) {ylog++; return 1;}
else if(strcmp(*argv,"-zl")==0) {zlog++; threed++; return 1;}
else if(strcmp(*argv, "-3")==0) {threed++; return 1;}
else gripe(argv);
}
get_double(argc,argv,permitted,a,b,c)
int argc,permitted; char **argv; double *a,*b,*c;
{ int i=1;
if((permitted--)>0 && (argc>i) && numeric(argv[i])) *a=atof(argv[i++]);
if((permitted--)>0 && (argc>i) && numeric(argv[i])) *b=atof(argv[i++]);
if((permitted--)>0 && (argc>i) && numeric(argv[i])) *c=atof(argv[i++]);
return i;
}
gripe_arg(s) char *s;
{ fprintf(stderr,"argument missing for switch %s",s);
help();
}
gripe(argv) char **argv;
{ fprintf(stderr,*argv); fprintf(stderr," isn\'t a legal argument \n\n");
help();
}
char *msg[]=
{"smooth version ", VERSION, "\n",
"\nusage: smooth [file] [options]\n",
"options are:\n",
" -a [step [start]] automatic abscissas \n",
" -b break smooth after each label \n",
" -c general curve \n",
" -f <num> fraction of points to use for each fitted value (default .5)\n",
" -n <num> number of points to use for each fitted value (default 50%%)\n",
" -r print residuals rather than smoothed values\n",
" -s split linear fit rather than \"lowness\"\n",
" -xl take logs of x values before smoothing \n",
" -yl take logs of y values before smoothing \n",
" -zl take logs of z values before interpolating \n",
" (implies -3)\n",
" -3 3D case: x, y, and z given for each point\n",
"\n",
"Default smoothing method is \"lowness\": robust locally weighted \n",
"regression & smoothing \n",
0
};
help()
{ char **s;
s=msg;
while(*s) printf(*s++);
exit(1);
}
numeric(s) char *s;
{ char c;
while(c=*s++)
{if((c<='9' && c>='0') || c=='+' || c=='-' || c=='.') continue;
return 0;
}
return 1;
}
char *gmem(size) unsigned int size;
{ char *p;
void *malloc();
p=(char *)malloc(size);
if(!p)
{fprintf(stderr,"can\'t allocate temporary storage of %u\n",size);
exit(1);
}
return p;
}
fpcompare(r, s) double *r, *s;
{ double d;
d=*r-*s;
if(d<0.) return -1;
if(d>0.) return 1;
return 0;
}
/*
Lowness
Robust locally weighted regression is a method for smoothing a
scatterplot, (x[i], y[i]), i=1,...,n, in which the fitted value
at x[k] is the value of a polynomial fit to the data using
weighted least squares, where the weight for (x[i], y[i]) is
large if x[i] is close to x[k]. Robustness is added by
calculating residuals and repeating the procedure with reduced
weights on points with large residuals.
Reference:
W. S. Cleveland, "Robust Locally Weighted Regression and
Smoothing Scatterplots", Journal of the American Statistical
Association, v74, n368, p829 (Dec 79)
*/
lowness(n, x, y, ys) int n; double *x, *y, *ys;
{ double *t, *r, *w, d, d1, u, m, m6i, sum, a[2];
int i, j, k;
num_fitted=floor(fraction_fitted*n+.5);
t=(double *)gmem(num_fitted*sizeof(double));
r=w=(double *)gmem(n*sizeof(double)); /* r and w share space */
k=0;
for (i=0; i<n; i++)
{if(i==0 || x[i]!=x[i-1])
{while(k+num_fitted<n && (x[i]-x[k] > x[k+num_fitted]-x[i])) k++;
d=x[i]-x[k]; d1=x[k+num_fitted-1]-x[i];
if(d1>d) d=d1;
if(d==0.)
{sum=0.;
for (j=0; j<num_fitted; j++) sum += y[i+j];
a[0]=sum/num_fitted; a[1]=0.;
}
else
{for (j=0; j<num_fitted; j++) /* calculate tricube weighting */
{u=fabs(x[i]-x[k+j])/d; u=1.-u*u*u; t[j]=u*u*u;
}
lin(num_fitted, x+k, t, y+k, a);
}
}
ys[i]=r[i]=fabs(y[i]-(a[0]+a[1]*x[i]));
}
/* sorting to find median value - although it's overkill */
qsort(ys, n, sizeof(double), fpcompare);
m=ys[n/2];
if(m==0.) /* input function is already linear - can't smooth any more */
{for (i=0; i<n; i++) ys[i]=y[i];
free(t); free(w);
return;
}
m6i=1./(6.*m);
for (i=0; i<n; i++)
{u=r[i]*m6i;
if(u<1.) {u=1.-u*u; w[i]=u*u;}
else w[i]=0.;
}
k=0;
for (i=0; i<n; i++)
{if(i==0 || x[i]!=x[i-1])
{while(k+num_fitted<n && (x[i]-x[k] > x[k+num_fitted]-x[i])) k++;
d=x[i]-x[k]; d1=x[k+num_fitted-1]-x[i];
if(d1>d) d=d1;
if(d==0.)
{sum=0.;
for (j=0; j<num_fitted; j++) sum += y[i+j];
a[0]=sum/num_fitted; a[1]=0.;
}
else
{for (j=0; j<num_fitted; j++) /* calculate tricube weighting */
{u=fabs(x[i]-x[k+j])/d; u=1.-u*u*u; t[j]=u*u*u*w[k+j];
}
lin(num_fitted, x+k, t, y+k, a);
}
}
ys[i]=a[0] + a[1]*x[i];
if(resid) ys[i]=y[i]-ys[i];
}
free(t); free(w);
}
/* lin - linear least squares fit */
lin(n, x, w, y, a)
int n; /* # points in x, w, or y */
double *x, /* independent variables */
*w, /* weights */
*y, /* dependent variables */
*a; /* resulting coeficients... y[i] = a[1]*x[i] + a[0] (approx) */
{ int i, j;
double sum, sumx, sumxx, sumy, sumxy, xw, cond, decomp();
static double d[2][2];
static int ipvt[2];
sum=sumx=sumxx=sumy=sumxy=0.;
for (i=0; i<n; i++)
{sum += *w;
sumx += (xw = *x * *w);
sumxx += *x * xw;
sumy += *y * *w;
sumxy += *y * xw;
x++; y++; w++;
}
d[0][0]=sum; d[0][1]=sumx; a[0]=sumy;
d[1][0]=sumx; d[1][1]=sumxx; a[1]=sumxy;
cond=decomp(2, 2, d, ipvt);
if(cond==(cond+1.))
{fprintf(stderr, "ill conditioned matrix");
/********
**********/
showv("x=", x-n, n);
showv("w=", w-n, n);
showv("y=", y-n, n);
printf("cond=%9.3e\n", cond);
exit(1);
}
solve(2, 2, d, a, ipvt);
}
showv(s,a,n) char *s; double a[]; int n;
{ int i,j;
printf("%s \n",s);
for (i=0; i<n; i++)
{printf("%8.4f ",a[i]);
if(i%8==7) printf("\n");
}
printf("\n");
}